﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Qiang.Geometry
{
    [Serializable]
    public class Coordinate
    {

        public Coordinate()
        {
            this._x = double.NaN;
            this._y = double.NaN;
            this._z = double.NaN;
        }


        public Coordinate(double x,double y)
        {
            this._x = x;
            this._y = y;
            this._z = double.NaN;
        }


        public Coordinate(double x, double y, double z)
        {
            this._x = x;
            this._y = y;
            this._z = z;
        }


        #region 属性

        protected double _x;

        /// <summary>
        /// X
        /// </summary>
        public double X
        {
            get { return _x; }
            set { _x = value; }
        }

        protected double _y;

        /// <summary>
        /// Y
        /// </summary>
        public double Y
        {
            get { return _y; }
            set { _y = value; }
        }

        protected double _z;

        /// <summary>
        /// Z
        /// </summary>
        public double Z
        {
            get { return _z; }
            set { _z = value; }
        }


        private double _m;

        /// <summary>
        /// M
        /// </summary>
        public double M
        {
            get { return _m; }
            set { _m = value; }
        }



        /// <summary>
        /// 维度
        /// </summary>
        public int Dimension
        {
            get 
            {
                return double.IsNaN(_z) ? 2 : 3;
            }
           
        }

        /// <summary>
        /// 
        /// </summary>
        public IEnvelope Evnelope
        {
            get
            {
                return new Envelope(this);
            }
        }
        

        public double this[int index]
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return X;
                    case 1:
                        return Y;
                    case 2:
                        return Z;
                    case 3:
                        return M;
                    default:
                        throw new IndexOutOfRangeException();
                }
            }
            set
            {
                switch (index)
                {
                    case 0:
                        X = value;
                        return;
                    case 1:
                        Y = value;
                        return;
                    case 2:
                        Z = value;
                        return;
                    case 3:
                        M = value;
                        return;
                    default:
                        throw new IndexOutOfRangeException();
                }
            }
        }


        #endregion

        
        #region 运算符

        public static Coordinate operator +(Coordinate pt1, Coordinate pt2)
        {
            if (pt1 == null || pt2 == null) return null;
            if (pt1.X == double.NaN || pt1.Y == double.NaN) return null;
            if (pt2.X == double.NaN || pt2.Y == double.NaN) return null;
            if (pt1.Z == double.NaN || pt2.Z == double.NaN)
                return new Coordinate(pt1.X + pt2.X, pt1.Y + pt2.Y);
            else
                return new Coordinate(pt1.X + pt2.X, pt1.Y + pt2.Y, pt1.Z + pt2.Z);
        }

                
        #endregion



        #region 方法

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pt"></param>
        /// <returns></returns>
        public bool Equals2D(Coordinate pt)
        {
            if (pt == null) return false;
            return _x == pt.X && _y == pt.Y;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pt"></param>
        /// <returns></returns>
        public bool Equals3D(Coordinate pt)
        {
            if (pt == null) return false;
            return _x == pt.X && _y == pt.Y && _z == pt.Z;
        }

        /// <summary>
        /// 距pt点的距度。
        /// </summary>
        /// <param name="pt"></param>
        /// <returns></returns>
        public double Distance(Coordinate pt)
        {
            double dx = pt.X - _x;
            double dy = pt.Y - _y;
            return Math.Sqrt(dx * dx + dy * dy);
        }



        #endregion



        # region 继承的方法


        public override bool Equals(object obj)
        {
            Coordinate objPt = obj as Coordinate;

            if (objPt == null)
            {
                return false;
            }

            if (double.IsNaN(this._z) || double.IsNaN(objPt.Z)) return (this._x == objPt._x && this._y == objPt._y);

            return (this._x == objPt._x && this._y == objPt._y && this._z == objPt._z);

        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }


        # endregion


    }
}
